import { join } from "path";
import { PathService } from "./pathService";
import { ShellService } from "./shellService";
import { ipcMain } from "electron";
import Logger from "electron-log";
import { v4 as uuidv4 } from 'uuid';

class NodeService {
    private shellService: ShellService;
    private pathService: PathService;
    private nodePath: string;
    private resourcesPath: string;
    private yarnPath: string;

    constructor() {
        this.shellService = new ShellService();
        this.pathService = new PathService();
        this.resourcesPath = this.pathService.resourcesRoot;
        this.nodePath = join(this.resourcesPath, "binarys/win/node/node.exe");
        this.yarnPath = join(this.resourcesPath, "binarys/win/node/yarn.cmd");
    }

    /**
     * 执行Node脚本（原有方法保持不变）
     */
    public exec(path: string, name: string, args: string = "") {
        return new Promise((resolve, reject) => {
            this.shellService.exec(`${this.nodePath} ${join(this.resourcesPath, path, name)} ${args}`, {
                cwd: join(this.resourcesPath, path)
            }).then(result => {
                resolve(result);
            }).catch(error => {
                reject(error);
            });
        });
    }

    /**
     * 流式执行Node脚本（新增方法）
     */
    public exec_stream(path: string, name: string, args: string = "", options: {
        onStdout?: (data: string) => void;
        onStderr?: (data: string) => void;
    } = {}) {
        return new Promise((resolve, reject) => {
            this.shellService.execStream(`${this.nodePath} ${join(this.resourcesPath, path, name)} ${args}`, {
                timeout: 1000 * 10,
                onStdout: options.onStdout,
                onStderr: options.onStderr
            }).then(result => {
                resolve(result);
            }).catch(error => {
                reject(error);
            });
        });
    }

    /**
     * 执行yarn命令（原有方法保持不变）
     */
    public run_yarn(path: string, args: string = "") {
        return new Promise((resolve, reject) => {
            this.shellService.exec(`${this.yarnPath} ${args}`, {
                cwd: join(this.resourcesPath, path),
                timeout: 1000 * 60 * 5
            }).then(result => {
                resolve(result);
            }).catch(error => {
                reject(error);
            });
        });
    }

    /**
     * 流式执行yarn命令（新增方法）
     */
    public run_yarn_stream(path: string, args: string = "", options: {
        onStdout?: (data: string) => void;
        onStderr?: (data: string) => void;
        timeout?: number;
    } = {}) {
        return new Promise((resolve, reject) => {
            this.shellService.execStream(`${this.yarnPath} ${args}`, {
                cwd: join(this.resourcesPath, path),
                timeout: options.timeout || 1000 * 60 * 5,
                onStdout: options.onStdout,
                onStderr: options.onStderr
            }).then(result => {
                resolve(result);
            }).catch(error => {
                reject(error);
            });
        });
    }
}

export function registerNodeIpc(service: NodeService) {
    // 原有IPC接口
    ipcMain.handle('node:exec', (_, path: string, name: string, args?: string) => service.exec(path, name, args));

    ipcMain.handle('node:run_yarn', (_, path: string, args?: string) => service.run_yarn(path, args));

    // 新增流式执行IPC接口
    ipcMain.handle('node:exec_stream', (event, path: string, name: string, args?: string) => {
        const execId = uuidv4(); // 生成唯一命令ID

        service.exec_stream(path, name, args, {
            onStdout: (data) => {
                event.sender.send(execId, { code: 0, data });
            },
            onStderr: (data) => {
                event.sender.send(execId, { code: 0, data });
            }
        }).then(() => {
            event.sender.send(execId, { code: 1, data: "finished" });
        }).catch(error => {
            event.sender.send(execId, { code: -1, data: error });
        });

        // 立即返回execId给渲染进程
        return execId;
    });

    ipcMain.handle('node:run_yarn_stream', (event, path: string, args?: string, timeout?: number) => {
        const execId = uuidv4(); // 生成唯一命令ID

        service.run_yarn_stream(path, args, {
            timeout: timeout || 1000 * 60 * 5,
            onStdout: (data) => {
                event.sender.send(execId, { code: 0, data });
            },
            onStderr: (data) => {
                event.sender.send(execId, { code: 0, data });
            }
        }).then(() => {
            event.sender.send(execId, { code: 1, data: "finished" });
        }).catch(error => {
            event.sender.send(execId, { code: -1, data: error });
        });

        return execId;
    });
}

export const nodeService = new NodeService();
